#include <iostream> //关于模板类的说明举例，包括各类数据结构、容器、迭代器和泛函等
#include <queue> //引入队列数据结构（标准库，但图没有标准库）
#include <stack> //引入栈数据结构
#include <deque> //引入双端队列数据结构库
#include <QMap>   //引入有序的映射标准库(Qt的)
#include <QDebug>
#include <Qset>
#include <set>
#include <algorithm>
#include <vector>
#include <list>
#include <tmp1.h>

int main(int argc, char *argv[])
{
   {std::queue<int> q; //定义一个队列数据结构
   q.push(0);  //加入元素（入列）
   q.push(1);
   q.push(2);

   // q ----->
   // 2 1 0

   auto print = [&q](){     //重载print
       std::cout << "head: " << q.front() << std::endl;
       std::cout << "rear: " << q.back() << std::endl;
   };

   print();
   q.pop();  //将队列的头一个取走（出列）
   print();  //因为堆q进行了.pop操作，所以这里重新打印会有变化
   }   //可以在main函数中任意添加中括号（包裹）

    {std::stack<int> s;  //定义一个栈型数据结构
    s.push(0);  //加入元素（入列）
    s.push(1);
    s.push(2);

    /**
     *
     *   2
     *   1
     *   0
     * s---
     *
     */

    // 2 1 0

    auto print = [&s](){     //重载print
        std::cout << "top: " << s.top() << std::endl;
    };

    print();
    s.pop();  //将栈顶的第一个取走（出列）
    print();  //因为堆q进行了.pop操作，所以这里重新打印会有变化
    }

    {
        std::deque<int> dq;
        //   (Head)->|||||||<-(Rear)
        dq.push_back(0);
        dq.push_front(100);

        std::cout <<dq.front() << std::endl;
        std::cout <<dq.back() << std::endl;

        dq.pop_back();
        dq.pop_front();

        std::cout <<dq.size() << std::endl;
    }

    {
        enum Color{
          Red,
          Yellow
        };

        QMap<std::string, Color> om;

        om.insert("Apple", Red);
        om.insert("Pear", Yellow);

        qDebug() << (om["Apple"] == Yellow);  //这里是恒等于（==），不是等于（=）
        qDebug() << (om["Pear"] == Yellow);
    }

    {
        auto print = [](QSet<int> s){  //重载print函数
            qDebug() << s;
        };

        QSet<int> a = {0, 1, 2, 4};   //这里Qt已经重载了加减等运算符，其中int是数据类型
        QSet<int> b = {0, 0, 1, 2, 6};

        print(a);
        print(b);

        print(a-b); //因为Qt已经重载了加减等运算符，所以相当于帮你做了很多脏活、累活
        print(a+b);
        print(a&b);

    }

    {
        auto print = [](std::set<int> s){  //重载print函数
            std::cout << "---set---" << std::endl;    //本来是无序的，所以不要进行排序。
            for(auto iter = s.begin(); iter != s.end(); ++ iter) {  //iter是迭代器，本身是个指针
                std::cout << (*iter) << std::endl;  //用*号来拿到指针（迭代器）里的数据
            }
        };

        std::set<int> a = {0, 1, 2, 4};   //int是数据类型
        std::set<int> b = {0, 0, 1, 2, 6};

        print(a);
        print(b);

//        std::set_intersection(a/begin(), a.end(), b.begin(), b.end());  //不太常用

//        print(a-b);
//        print(a+b);
//        print(a&b);

    }

    {
        Tmp1<double> ctmpl;             // 这里Tmp1是自己定义的模板类（实例化时指定为一个double类的ctmpl）
        auto r = ctmpl.add(1.00, 9.00); // 因为ctmpl是Tmp1实例化的类对象，所以这里可以调用Tmp1中的add函数。
        std::cout << r <<std::endl;

        //所以C++中类型（如Tmp1）是可以作为变量使用的，所以叫做模板类

        Tmp1<std::string> stmpl;    // 定义字符类时得加std,比如std::string
        auto s = stmpl.add("Hello,","World");
        std::cout << s <<std::endl;
    }

    {
        auto print = [](std::vector<int> s){  //重载print函数
            std::cout << "---vector---" << std::endl;   //打印一行“---vector---”
            for(auto iter = s.begin(); //(1)从容器的开头开始s.begin()
                iter != s.end()        //(2)如果没有遇到容器结尾s.end()，则继续迭代
                ; ++ iter) {           //(3)迭代器的步进
                std::cout << (*iter)   //(4)取出迭代器的内容，从这里可见迭代器本身就是一个指针！
                          << std::endl;
            }
        };

        auto sort = [&print](std::vector<int> s){ //重新排序
            std::sort(s.begin(), s.end());
            //std::sort(s.begin(), s.end() - 2); //结果00612，只重新排序了前三个，验证了end返回的是指针。
            //vector是连续内存是可以减两个的，但list等是非连续内存是不能减去的。
            print(s);
        };
        std::vector<int> b = {6, 0, 0, 1, 2};    //注意：vector没有互异性，所以结果里会有两个零（严格按顺序打印）
        print(b);
        sort(b);
    }

    {
        auto print = [](std::list<int> s){
            std::cout << "---list---" << std::endl;
            for(auto iter = s.begin(); iter != s.end(); ++ iter) {
                std::cout << (*iter) << std::endl;
            }
        };

        auto sort = [&print](std::list<int> s){ //重新排序
            s.sort(); //结果00612，只重新排序了前三个，验证了end返回的是指针。
            //vector是连续内存是可以减两个的，但list等是非连续内存是不能减去的,所以只能这么操作。
            print(s);
        };

        std::list<int> b = {6, 0, 0, 1, 2, 7};
        print(b);
        sort(b);
    }

    {
        auto print = [](std::deque<int> s){
            std::cout << "---deque---" << std::endl;
            for(auto iter = s.begin(); iter != s.end(); ++ iter) {
                std::cout << (*iter) << std::endl;
            }
        };

        auto sort = [&print](std::deque<int> s){ //重新排序
            std::sort(s.begin(), s.end());
            print(s);
        };

        std::deque<int> b = {10, 0, 1, 2, 6};
        print(b);
        sort(b);
    }

    return 0;
}
